package com.eastseeway.radioproject.gmn;

import android.app.Application;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.eastseeway.radioproject.base.BaseViewModel;
import com.eastseeway.radioproject.base.Const;
import com.eastseeway.radioproject.entities.BaseResponse;
import com.eastseeway.radioproject.entities.BaseTCPBean;
import com.eastseeway.radioproject.entities.Bean1FromHandle;
import com.eastseeway.radioproject.entities.BeanToBottomBoard;
import com.eastseeway.radioproject.entities.BeanToEnergyBoard;
import com.eastseeway.radioproject.entities.BottomBoardFunctionCode;
import com.eastseeway.radioproject.entities.ElectrodeInfoBean;
import com.eastseeway.radioproject.entities.OperationParams;
import com.eastseeway.radioproject.entities.UserInfo;
import com.eastseeway.radioproject.utils.ByteUtil;
import com.eastseeway.radioproject.utils.CommandGenerator;
import com.eastseeway.radioproject.utils.SPHelper;
import com.eastseeway.radioproject.utils.StructTransUtil;
import com.eastseeway.radioproject.utils.TimeUtils;
import com.google.gson.Gson;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import struct.StructException;

public class NPViewModel extends BaseViewModel<NPRepository> {
//    private final MutableLiveData<Byte> energyLiveData = new MutableLiveData<>((byte)20);
    private final MutableLiveData<Byte> frequency = new MutableLiveData<>((byte)1);

//    默认状态连续放电的时间和时间数值的索引位置
    private final MutableLiveData<Short> continuousDischargePeriod = new MutableLiveData<>((short)0);
    private final MutableLiveData<Integer> continuousDischargePosition = new MutableLiveData<>(0);
    //    出针模式
    private final MutableLiveData<Boolean> isAutoNeedleMode = new MutableLiveData<>(false);
    //    出针间隔 自动出针模式时，该参数才有意义
    private final MutableLiveData<Short> interval = new MutableLiveData<>((short)500);

    //    默认状态的刺入深度以及索引位置
    private final MutableLiveData<Byte> depth = new MutableLiveData<>((byte)4);
    private final MutableLiveData<Integer> depthPosition = new MutableLiveData<>(0);
    //  剩余次数
    private final MutableLiveData<Short> shengyucishu = new MutableLiveData<>((short)5000);

    private LiveData<List<OperationParams>> operationParamsList = new MutableLiveData<>();
    private MutableLiveData<List<OperationParams>> operationParamsListFromSP = new MutableLiveData<>();

    private final MutableLiveData<Boolean> isStandByState = new MutableLiveData<>(true);
    private final MutableLiveData<Boolean> isWorkingState = new MutableLiveData<>(false);
    private final MutableLiveData<Integer> idp = new MutableLiveData<>(6);
    private final MutableLiveData<Integer> idhp = new MutableLiveData<>(60);
    private final MutableLiveData<Integer> idlp = new MutableLiveData<>(80);
    private final MutableLiveData<Boolean> isIntermittentMode = new MutableLiveData<>();
//    是否处于预置参数模式
    private final MutableLiveData<Boolean> isPreMode = new MutableLiveData<>(false);
    public String[] autoTypes = {"foot","auto0.5","auto1","auto2"};
    private final MutableLiveData<Integer> index = new MutableLiveData<>(0);
    private byte energy = 6;
    private final MutableLiveData<Boolean> isMJ = new MutableLiveData<>(true);

    public NPViewModel(@NonNull Application application) {
        super(application);
    }

    @Override
    protected NPRepository setRepository() {
        return new NPRepository();
    }

    void sendHandleCommand(){
        try {
            byte[] handleCommand = CommandGenerator.commandData1ToHandle2(Const.ADDRESS_TO_HANDLE_2_DATA_1, getFrequency().getValue(), energy, getDepth().getValue(), getIsAutoNeedleMode().getValue(),
                    interval.getValue(),getContinuousDischargePeriod().getValue(), getIdp().getValue().byteValue(), getIdhp().getValue().byteValue(), getIdlp().getValue().byteValue(), getIsWorkingState().getValue(),
                    getIsIntermittentMode().getValue() ,shengyucishu.getValue());
            sendMessage(handleCommand);
            saveDataToFile("np:handle command "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new Bean1FromHandle(),handleCommand)));
        }catch (StructException e){
            throw new RuntimeException(e);
        }
    }
    void sendPreCommand(){
        try {
            byte[] energyCommand = CommandGenerator.commandToEnergyBoard(Const.ADDRESS_TO_ENERGY_BOARD, getFrequency().getValue(),getIsIntermittentMode().getValue(),getIsStandByState().getValue(),getIdp().getValue() );

            String vBusValue = mRepository.getVBusValue("0" + frequency.getValue() + energy);
            if (vBusValue == null) {
                vBusValue = "8";
            }
            float vBusVoltage = Float.parseFloat(vBusValue);
            byte[] bottomBoardCommand = CommandGenerator.command2BottomBoard(Const.ADDRESS_TO_BOTTOM_BOARD, BottomBoardFunctionCode.cmd_bottombrd_Vbus_Set, (short) (vBusVoltage*100));
//            Log.e("12121", "sendPreCommandNP: freq:"+getFrequency().getValue()+";断续模式："+getIsIntermittentMode().getValue()+";是否待机："+getIsStandByState().getValue()+";能量："+energy+";电压："+vBusVoltage+";idp:"+getIdp().getValue());
            ByteBuffer buffer = ByteBuffer.allocate(energyCommand.length + bottomBoardCommand.length);
            buffer.put(energyCommand);
            buffer.put(bottomBoardCommand);
            sendMessage(buffer.array());
            saveDataToFile("np:pre command ToEnergyBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToEnergyBoard(),energyCommand)));
//            saveDataToFile("np:pre command ToEnergyBoard "+new Gson().toJson(StructTransUtil.unpack(new BeanToEnergyBoard(),StructTransUtil.unpack(new BaseTCPBean(),energyCommand).getContent())));
            saveDataToFile("np:pre command ToBottomBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToBottomBoard(),bottomBoardCommand)));
//            saveDataToFile("np:pre command ToBottomBoard "+new Gson().toJson(StructTransUtil.unpack(new BeanToBottomBoard(),StructTransUtil.unpack(new BaseTCPBean(),bottomBoardCommand).getContent())));
        } catch (StructException e) {
            throw new RuntimeException(e);
        }
    }


    void resetState() {
        try  {
            byte[] commandToBottomBoard = CommandGenerator.command2BottomBoard(Const.ADDRESS_TO_BOTTOM_BOARD, BottomBoardFunctionCode.cmd_bottombrd_Vbus_Set, (short) 0);
            byte[] commandToEnergyBoard = CommandGenerator.commandToEnergyBoard(Const.ADDRESS_TO_ENERGY_BOARD, getFrequency().getValue(),getIsIntermittentMode().getValue(), true,  getIdp().getValue());
            byte[] handleCommand = CommandGenerator.commandData1ToHandle2(Const.ADDRESS_TO_HANDLE_2_DATA_1, getFrequency().getValue(), energy, getDepth().getValue(), getIsAutoNeedleMode().getValue(), interval.getValue(),
                    getContinuousDischargePeriod().getValue(), getIdp().getValue().byteValue(), getIdhp().getValue().byteValue(), getIdlp().getValue().byteValue(), false, getIsIntermittentMode().getValue() ,shengyucishu.getValue());

            sendMessage(commandToBottomBoard);
            sendMessage(commandToEnergyBoard);
            sendMessage(handleCommand);
            saveDataToFile("np:reset state ToBottomBoard "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToBottomBoard(),commandToBottomBoard)));
            saveDataToFile("np:reset state ToEnergyBoard "+ new Gson().toJson(StructTransUtil.convertByteArrayToString(new BeanToEnergyBoard(),commandToEnergyBoard)));
            saveDataToFile("np:reset state ToHandle "+new Gson().toJson(StructTransUtil.convertByteArrayToString(new Bean1FromHandle(),handleCommand)));

        } catch (StructException e) {
            throw new RuntimeException(e);
        }

    }

    void saveParamsToFile(String title){
        saveDataToFile(title + File.separator +getCurrentParams());
    }

    public void saveDataToFile(String msg){
        mRepository.saveData(msg);
    }

    String getCurrentParams(){
        OperationParams operationParams = new OperationParams("",
                SPHelper.getCurrentUserInfo(getApplication()).getName(),
                0,
                TimeUtils.getCurrentTime(TimeUtils.FORMAT_DATE_TIME_FULL1),
                false,
                false,
                getFrequency().getValue(),
                energy,
                getDepth().getValue(),
                getDepthPosition().getValue(),
                (byte) 0,
                getIsIntermittentMode().getValue(),
                getIdp().getValue().byteValue(),
                getIdhp().getValue().byteValue(),
                getIdlp().getValue().byteValue(),
                getContinuousDischargePeriod().getValue().shortValue(),
                getContinuousDischargePosition().getValue(),
                getIsAutoNeedleMode().getValue(),
                getInterval().getValue().shortValue(),
                shengyucishu.getValue());
        return new Gson().toJson(operationParams);
    }

//    @SuppressLint("NonConstantResourceId")
//    public void onCheckedChangeListener(boolean isChecked){
//        playSound();
//        Log.e("12121","onCheckedChangeListener: "+isChecked);
//    }

    public void changeAutoMode(){
        playSound();
        if (index.getValue() < 3) index.setValue(index.getValue()+1);
        else index.setValue(0);

        switch (index.getValue()) {
            case 0:
                isAutoNeedleMode.setValue(false);
                break;
            case 1:
                isAutoNeedleMode.setValue(true);
                interval.setValue((short) 500);
                break;
            case 2:
                isAutoNeedleMode.setValue(true);
                interval.setValue((short) 1000);
                break;
            case 3:
                isAutoNeedleMode.setValue(true);
                interval.setValue((short) 2000);
                break;
        }

        if (index.getValue() == 0) {
            //do nothing
        }else {
            isAutoNeedleMode.setValue(true);
        }
    }

    public MutableLiveData<Boolean> getIsAutoNeedleMode() {
        return isAutoNeedleMode;
    }

    public MutableLiveData<Short> getInterval() {
        return interval;
    }


    public void replaceElectrode() {
        try {
            byte[] bytes = CommandGenerator.commandReplaceElectrode(Const.ADDRESS_TO_HANDLE_2_DATA_1);
            sendMessage(bytes);
        } catch (StructException e) {
            throw new RuntimeException(e);
        }
    }


    public void setEnergy(byte energy) {
        this.energy = energy;
//        energyLiveData.setValue(energy);
    }

    public byte getEnergy() {
        return energy;
    }

    void saveQuickOperationParam(UserInfo userInfo, int position){
        OperationParams operationParams = new OperationParams(
                CommandGenerator.generateId(userInfo.getId(),false,position),
                userInfo.getName(),
                position,
                TimeUtils.getCurrentTime(TimeUtils.FORMAT_DATE_TIME_FULL1),
                false,
                false,
                getFrequency().getValue(),
                energy,
                getDepth().getValue(),
                getDepthPosition().getValue(),
                (byte) 0,
                getIsIntermittentMode().getValue(),
                getIdp().getValue().byteValue(),
                getIdhp().getValue().byteValue(),
                getIdlp().getValue().byteValue(),
                getContinuousDischargePeriod().getValue(),
                getContinuousDischargePosition().getValue(),
                getIsAutoNeedleMode().getValue(),
                getInterval().getValue().shortValue(),
                shengyucishu.getValue()
        );
        Log.e("12121","updateOperationParam "+new Gson().toJson(operationParams));
        mRepository.updateOperationParams(operationParams);
    }

    void queryOperationParams(UserInfo userInfo){
        operationParamsList = mRepository.queryOperationParams(userInfo.getName());
    }

    public LiveData<List<OperationParams>> getOperationParamsList() {
        return operationParamsList;
    }

    public MutableLiveData<Byte> getDepth() {
        return depth;
    }

    public void changeFrequency(){
        playSound();
        frequency.setValue(frequency.getValue()==1?(byte)2:(byte)1);
//        每次切换频率时，需要停止能量板
    }

    public MutableLiveData<Byte> getFrequency() {
        return frequency;
    }

//    改变待机状态和准备状态
    public void changeWorkState() {
        this.isStandByState.setValue(Boolean.FALSE.equals(getIsStandByState().getValue()));
    }

    public MutableLiveData<Boolean> getIsStandByState() {return isStandByState;}
    public MutableLiveData<Boolean> getIsWorkingState() {return isWorkingState;}

    public MutableLiveData<Short> getShengyucishu() {return shengyucishu;}

    public MutableLiveData<Integer> getIdp() {return idp;}

    public MutableLiveData<Integer> getIdhp() {
        return idhp;
    }

    public MutableLiveData<Integer> getIdlp() {
        return idlp;
    }

    public MutableLiveData<Short> getContinuousDischargePeriod() {return continuousDischargePeriod;}

    public MutableLiveData<Boolean> getIsIntermittentMode() {return isIntermittentMode;}

    public MutableLiveData<Integer> getContinuousDischargePosition() {return continuousDischargePosition;}

    public MutableLiveData<Integer> getDepthPosition() {return depthPosition;}
    public MutableLiveData<Integer> getIndex() {return index;}
    public MutableLiveData<Boolean> getIsPreMode() {return isPreMode;}
    public void checkElectrode(String deviceid){
        mRepository.checkElectrode(deviceid).enqueue(new Callback<BaseResponse<ElectrodeInfoBean>>() {
            @Override
            public void onResponse(Call<BaseResponse<ElectrodeInfoBean>> call, Response<BaseResponse<ElectrodeInfoBean>> response) {

            }

            @Override
            public void onFailure(Call<BaseResponse<ElectrodeInfoBean>> call, Throwable throwable) {

            }
        });
    }

    public void changeEnergyUnit(){
        isMJ.setValue(Boolean.FALSE.equals(isMJ.getValue()));
    }

    public MutableLiveData<Boolean> getIsMJ() {
        return isMJ;
    }


}
